function route (method, fn) {
    return {
        method: method,
        handler: fn
    }
}

/**
@param {{
(
    ctx: {
        query: object;
        request: { body: object; };
        success: (data?: object) => void;
        error: (code: object, data?: object) => void;
    },
    next?: () => Promise<void>
): Promise<void>}[]} fn
 * **/
exports.get = function (...fn) {
    return route('get', fn)
}

/**
@param {{
(
    ctx: {
        query: object;
        request: { body: object; };
        success: (data?: object) => void;
        error: (code: object, data?: object) => void;
    },
    next?: () => Promise<void>
): Promise<void>}[]} fn
* **/
exports.post = function (...fn) {
    return route('post', fn)
}


/**
@param {{
(
    ctx: {
        query: object;
        request: { body: object; };
        success: (data?: object) => void;
        error: (code: object, data?: object) => void;
    },
    next?: () => Promise<void>
): Promise<void>}[]} fn
* **/
exports.put = function (...fn) {
    return route('put', fn)
}

/**
@param {{
(
    ctx: {
        query: object;
        request: { body: object; };
        success: (data?: object) => void;
        error: (code: object, data?: object) => void;
    },
    next?: () => Promise<void>
): Promise<void>}[]} fn
* **/
exports.del = function (...fn) {
    return route('del', fn)
}

/**
@param {{
(
    ctx: {
        query: object;
        request: { body: object; };
        success: (data?: object) => void;
        error: (code: object, data?: object) => void;
    },
    next?: () => Promise<void>
): Promise<void>}[]} fn
* **/
exports.head = function (...fn) {
    return route('head', fn)
}

/**
@param {{
(
    ctx: {
        query: object;
        request: { body: object; };
        success: (data?: object) => void;
        error: (code: object, data?: object) => void;
    },
    next?: () => Promise<void>
): Promise<void>}[]} fn
* **/
exports.all = function (...fn) {
    return route('all', fn)
}

function formatName (name) {
    return name.replace(/([A-Z])/g, '-$1').replace(/^-/, '').toLowerCase()
}

exports.autoRegister = function (router, controllers, perfix = '') {
    const routes = {}

    for (const moduleName in controllers) {
        const m = formatName(moduleName)
        routes[moduleName] = []

        for (const handlerName in controllers[moduleName]) {
            const handler = controllers[moduleName][handlerName]
            const action = formatName(handlerName)

            if (handler.method) {
                const args = handler.handler.map(e => e)
                const path = `${perfix}/${m}/${action}`
                args.unshift(path)
                routes[moduleName].push(`${handler.method.toUpperCase()} ${path}`)
                router[handler.method].apply(router, args)
                console.log(handler.method, path)
            }
        }
    }

    router.get('/api', async ctx => {
        ctx.body = routes
    })
}
